package org.softee.extractor.transform;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

/**
 * This test was written to reproduce a bug that exists in Java SE, where exceptions are thrown when using a StaxSource
 * to parse certain wellformed XML instances.
 *
 * Bug has been reproduced with the following Java versions:
 * - 1.6.0_29-b11-402-11M3527 (Mac OS X, 10.7.2)
 * - 1.7.0_04-ea-b13 (Mac OS X, 10.7.2)
 *
 * The bug has been previously reported http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7148925
 */
@Ignore
public class StaxSourceParsingBug {
    /** Succeeds StAXSource processing */
    private static final String XML_1 = "<root/>";

    /** Succeeds StAXSource processing */
    private static final String XML_2 = "<!DOCTYPE root [<!ENTITY et 'Come Home'>]><root et='&et;'/>";

    /** Fails StAXSource processing with java.lang.IllegalStateException */
    private static final String XML_3 = "<?xml-stylesheet href='show.xsl' type='text/html'?><root/>";

    /** Succeeds StAXSource processing */
    private static final String XML_4 = "<?xml version='1.0'?><?xml-stylesheet href='show.xsl' type='text/html'?><root/>";

    /** Fails StAXSource processing with javax.xml.transform.TransformerException */
    private static final String XML_5 = "<?xml version='1.0'?><?xml-stylesheet href='show.xsl' type='text/html'?><!DOCTYPE root><root/>";

    /** Succeeds StAXSource processing */
    private static final String XML_6 = "<?xml version='1.0'?><!DOCTYPE root [<!ELEMENT greeting (#PCDATA)>]><root/>";

    /** Fails StAXSource processing with javax.xml.transform.TransformerException */
    private static final String XML_7 = "<?xml version='1.0'?><?xml-stylesheet href='show.xsl' type='text/html'?><!DOCTYPE root [<!ELEMENT greeting (#PCDATA)>]><root/>";

    TransformerFactory tf = TransformerFactory.newInstance();

    @BeforeClass
    public static void beforeClass() {
        //System.getProperties().list(System.out);
        showProperty("java.version");
        showProperty("java.runtime.version");
        showProperty("os.name");
        showProperty("os.version");

    }

    private static void  showProperty(String name) {
        System.out.printf("%s = %s%n", name, System.getProperty(name));
    }
    @Test
    public void testParseStreamSource() throws Exception {
        parseStreamSource(XML_1);
        parseStreamSource(XML_2);
        parseStreamSource(XML_3);
        parseStreamSource(XML_4);
        parseStreamSource(XML_5);
        parseStreamSource(XML_6);
        parseStreamSource(XML_7);
    }

    @Test
    public void testParseStaxSource1() throws Exception {
        parseStaxSource(XML_1);
    }

    @Test
    public void testParseStaxSource2() throws Exception {
        parseStaxSource(XML_2);
    }

    /**
     * Fails with:
     * java.lang.IllegalStateException: StAXSource(XMLStreamReader) with XMLStreamReader not in
     *    XMLStreamConstants.START_DOCUMENT or XMLStreamConstants.START_ELEMENT state
     */
    @Test
    public void testParseStaxSource3() throws Exception {
        parseStaxSource(XML_3);
    }

    @Test
    public void testParseStaxSource4() throws Exception {
        parseStaxSource(XML_4);
    }

    /**
     * Fails with:
     * javax.xml.transform.TransformerException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,105]
     * Message: found: DTD, expected START_ELEMENT or END_ELEMENT
     */
    @Test
    public void testParseStaxSource5() throws Exception {
        parseStaxSource(XML_5);
    }

    @Test
    public void testParseStaxSource6() throws Exception {
        parseStaxSource(XML_6);
    }

    /**
     * Fails with:
     * javax.xml.transform.TransformerException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,105]
     * Message: found: DTD, expected START_ELEMENT or END_ELEMENT
     */
    @Test
    public void testParseStaxSource7() throws Exception {
        parseStaxSource(XML_7);
    }

    private void parseStreamSource(String xml) throws Exception {
        Source source = new StreamSource(new StringReader(xml));
        unityTransform(source, xml);
    }

    private void parseStaxSource(String xml) throws Exception {
        XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new StringReader(xml));
        StAXSource source = new StAXSource(xmlStreamReader);
        unityTransform(source, xml);
    }

    private void unityTransform(Source source, String sourceXml) throws Exception{
        StringWriter sw = new StringWriter();
        Result result = new StreamResult(sw);
        tf.newTransformer().transform(source, result);
        System.out.printf("%n%s:%nSource: %s%nResult: %s%n", source.getClass().getSimpleName(), sourceXml, sw);
    }
}
